package com.lin.filegraph.utils.comcheck;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 15:51
 */

import com.lin.filegraph.utils.compdg.ComponentEdge;
import com.lin.filegraph.utils.compdg.ComponentGraph;
import com.lin.filegraph.utils.compdg.ComponentNode;
import com.lin.filegraph.utils.model.ComponentModule;
import com.lin.filegraph.utils.model.Module;
import com.lin.filegraph.utils.name.ComRename;
import com.lin.filegraph.utils.name.DirSimilarity;
import com.lin.filegraph.utils.threshold.Threshold;

import java.util.ArrayList;
import java.util.List;

public class DirCheck {

    public static void executeDirCheck(ComponentGraph graph, List<Module> comList, List<ComponentModule> fileList) {
        checkSeparate(graph,comList,fileList);
        checkSame(graph);
    }

    /**
     * 优化独立组件
     */
    private static void checkSeparate(ComponentGraph graph,List<Module> comList,List<ComponentModule> fileList) {
        List<ComponentNode> comsSeparate = new ArrayList<>();
        for (ComponentNode cn : graph.getAllComponents()) {
            //排除separate组件
            if(cn.isFeature()==true)
                continue;
            // 找到独立组件下的子目录
            if (graph.getPostComponents(cn).size() == 0 && graph.getPreComponents(cn).size() == 0) {
                if (cn.getAllFiles().get(0) != null) {
                    comsSeparate.add(cn);
                }
            }
        }

        unionSameCom(graph, comsSeparate);
        System.out.println("独立组件与非独立合并");
        comsSeparate.clear();
        for (ComponentNode cn : graph.getAllComponents()) {
            // 找到独立组件下的子目录
            if (graph.getPostComponents(cn).size() == 0 && graph.getPreComponents(cn).size() == 0 && cn.getAllFiles().size() < Threshold.MINCOM) {
                if (cn.getAllFiles().get(0) != null&&cn.isFeature()==false) {
                    comsSeparate.add(cn);
                }
            }
        }
        for (int i = comsSeparate.size() - 1; i >= 0; i--) {
            ComponentNode cnS = comsSeparate.get(i);
            double maxSim = 0;
            ComponentNode tNode = null;
            for (ComponentNode cn : graph.getAllComponents()) {
                if (cnS != cn&&cn.isFeature()==false) {
                    double sim = DirSimilarity.getSimLevelOfNode(cnS, cn);
                    if (sim > Threshold.reNameSep) {
                        if (sim > maxSim || (sim == maxSim && tNode.getAllFiles().size() > cn.getAllFiles().size())) {
                            maxSim = sim;
                            tNode = cn;
                        }
                    }
                }

            }
            if (tNode != null)
                graph.mergeNodes(tNode, cnS);
        }

    }

    private static void unionSameCom(ComponentGraph graph, List<ComponentNode> comsSeparate) {
        // 同名独立组件聚合
        System.out.println("******独立组件间同名聚合*****");
        for (int i = comsSeparate.size() - 1; i >= 0; i--) {
            ComponentNode cnS = comsSeparate.get(i);
            if(cnS.isFeature()==true)
                continue;
            ComponentNode temp = null;
            double max = 0;
            for (int j = i - 1; j >= 0; j--) {
                ComponentNode cn = comsSeparate.get(j);
                if(cn.isFeature()==true)
                    continue;
                double sim = DirSimilarity.getSimLevelOfNode(cnS, cn);
                if (sim >0 && sim > max) {
                    temp = cn;
                    max = sim;
                }
            }

            if (max != 0&&temp!=null) {
                graph.mergeNodes(temp, cnS);
                comsSeparate.remove(cnS);
                temp.reComName(ComRename.getComNameByDir(temp));
            }
        }
    }

    /**
     * 同名组件优化
     */
    private static void checkSame(ComponentGraph graph) {
        boolean isUnoin=false;
        for (ComponentEdge cEdge : graph.getAllComponentEdges()) {
            ComponentNode cn1 = cEdge.getPreComponent();
            ComponentNode cn2 = cEdge.getPostComponent();
            if(cn1.isFeature()==true&&cn2.isFeature()==true)
                continue;
            double sim = DirSimilarity.getSimLevelOfNode(cn1, cn2);
            //相似度超过0.3，同时有一个比较小的组件
            if(!cn1.equals(cn2))
                if(isSize(cn1, cn2, graph)){
                    if (sim > Threshold.reNameSep) {
                        graph.mergeNodes(cn1, cn2);
                        isUnoin=true;
                        break;
                    }else if (cn1.getAllFiles().size() < Threshold.MINMINCOM || cn2.getAllFiles().size() < Threshold.MINMINCOM) {
                        //				if (ClusterPreJudge.enableCluster(cn1, cn2, graph)) {
                        graph.mergeNodes(cn1, cn2);
                        isUnoin=true;
                        break;
                        //				}
                    }
                }
        }
        if(isUnoin)
            checkSame(graph);

    }

    private static boolean isSize(ComponentNode cn1,ComponentNode cn2,ComponentGraph graph){
        if(cn1.getAllFiles().size() < Threshold.MINCOM || cn2.getAllFiles().size() < Threshold.MINCOM)
            if((cn1.getAllFiles().size()+cn2.getAllFiles().size())<graph.getTotalSize()*Threshold.comScale2)
                return true;
        return false;

    }

}

